﻿using SuperMap.Data;
using SuperMap.Realspace;
using SuperMap.UI;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;
using Ycjw.PipeLine.Map.Basic.SuperMap;
using Ycjw.PipeLine.Map.Tools.Conditions.JJAnalysts;

namespace Ycjw.PipeLine.Scenes
{
    /****************************************************************************************/
    /*
    功    能:放置三维场景的DocWindow
    作    者: RenZachary
    联系方式: rzcgis@foxmail.com（QQ455745253）
    生成日期: 2021年3月24日
    修改日志: 
    版权说明: @2021 西安云创经纬信息科技有限公司 版权所有 All right reserved.
    注    意: 本内容仅限于云创经纬公司内部使用，禁止用于商业目的。
    */
    /****************************************************************************************/
    public class SceneSetting:SceneOperInterface
    {
        private readonly new FormMainRibbon m_FormMain;
        private Workspace Workspace
        {
            get
            {
                return m_SceneControl.Scene.Workspace;
            }
        }
        public SceneControl SceneControl
        {
            get
            {
                return m_SceneControl;
            }
            set
            {
                m_SceneControl = value;
            }
        }
        
        // 地下模式参数
        // Underground mode parameters
        private GeoStyle3D m_Style3d;

        // 定义存储字符串的变量
        // Define variable to store string
        private String m_SquareMeter = "平方米";
        private String m_Area = "挖方面积：";
        // 标示填挖方的区域
        // Mark cutting area
        private Int32 m_Index = -1;

        private TextureForm m_TextureForm;

        private readonly Theme3DCustom m_Theme3DCustom;

        private readonly Layer3DDataset m_Layer3DDataset;

        // Scene Element
        #region 场景元素
        /// <summary>
        /// 获取或设置场景太阳可见性
        /// Get or set the sun visibility
        /// </summary>
        public Boolean Sun
        {
            get { return m_SceneControl.Scene.Sun.IsVisible; }
            set
            {
                m_SceneControl.Scene.Sun.IsVisible = value;
                m_SceneControl.Scene.Refresh();
            }
        }
        /// <summary>
        /// 获取或设置场景海洋可见性
        /// Get or set the ocean visibility
        /// </summary>
        public Boolean Ocean
        {
            get { return m_SceneControl.Scene.Ocean.IsVisible; }
            set
            {
                m_SceneControl.Scene.Ocean.IsVisible = value;
                m_SceneControl.Scene.Refresh();
            }
        }
        /// <summary>
        /// 获取或设置场景雾可见性
        /// Get or set the fog visibility
        /// </summary>
        public Boolean Fog
        {
            get { return m_SceneControl.Scene.Fog.IsEnabled; }
            set
            {
                m_SceneControl.Scene.Fog.IsEnabled = value;
                if (value)
                {
                    m_SceneControl.Scene.FogVisibleAltitude = 1000000000;
                    m_SceneControl.Scene.Fog.Color = Color.White;
                }
                else
                {
                    m_SceneControl.Scene.FogVisibleAltitude = 1;
                    m_SceneControl.Scene.Fog.Color = Color.Transparent;
                }
                m_SceneControl.Scene.Refresh();
            }
        }
        /// <summary>
        /// 获取或设置场景比例尺可见性
        /// Get or set the scale visibility
        /// </summary>
        public Boolean ScaleLegend
        {
            get { return m_SceneControl.Scene.IsScaleLegendVisible; }
            set { m_SceneControl.Scene.IsScaleLegendVisible = value; }
        }
        /// <summary>
        /// 获取或设置场景经纬网可见性
        /// Get or set the lat/lon visibility
        /// </summary>
        public Boolean LatLonGrid
        {
            get { return m_SceneControl.Scene.LatLonGrid.IsVisible; }
            set { m_SceneControl.Scene.LatLonGrid.IsVisible = value; }
        }
        /// <summary>
        /// 获取或设置场景经纬网文字可见性
        /// Get or set the lat/lon text visibility
        /// </summary>
        public Boolean LatLonGridText
        {
            get { return m_SceneControl.Scene.LatLonGrid.IsTextVisible; }
            set { m_SceneControl.Scene.LatLonGrid.IsTextVisible = value; }
        }
        /// <summary>
        /// 获取或设置状态栏可见性
        /// Get or set status bar visibility
        /// </summary>
        public Boolean StatusBar
        {
            get { return m_SceneControl.IsStatusBarVisible; }
            set { m_SceneControl.IsStatusBarVisible = value; }
        }
        /// <summary>
        /// 获取或设置导航栏可见性
        /// Get or set navigation visibility
        /// </summary>
        public Boolean Navigation
        {
            get { return m_SceneControl.NavigationControl.IsVisible; }
            set { m_SceneControl.NavigationControl.IsVisible = value; }
        }
        /// <summary>
        /// 获取或设置大气的可见性
        /// Get or set atmosphere visibility
        /// </summary>
        public Boolean Atmosphere
        {
            get { return m_SceneControl.Scene.Atmosphere.IsVisible; }
            set { m_SceneControl.Scene.Atmosphere.IsVisible = value; }
        }
        /// <summary>
        /// 获取或设置地下模式的可见性
        /// Get or set the underground mode visibility
        /// </summary>
        public Boolean Underground
        {
            get { return m_SceneControl.Scene.Underground.IsVisible; }
            set
            {
                m_Style3d = new GeoStyle3D();
                if (value)
                {
                    m_Style3d.AltitudeMode = AltitudeMode.RelativeToUnderground;
                    m_SceneControl.Scene.Underground.Depth = 200;
                }
                else
                {
                    m_Style3d.AltitudeMode = AltitudeMode.RelativeToGround;
                }
                m_SceneControl.Scene.Underground.IsVisible = value;

            }
        }
        /// <summary>
        /// 获取或设置场景地球透明度
        /// Get or set the global opacity
        /// </summary>
        public Int32 Transparency
        {
            get { return m_SceneControl.Scene.GlobalImage.Transparency; }
            set { m_SceneControl.Scene.GlobalImage.Transparency = value >= 100 ? 100 : value; }
        }
        #endregion

        /// <summary>
        /// 根据workspace和sceneControl构造 SampleRun对象
        /// Build SampleRun according to workspace and sceneControl
        /// </summary>
        public SceneSetting(SceneControl sceneControl,FormMainRibbon mainfForm) : base(sceneControl, mainfForm)
        {
            try
            {
                m_FormMain = mainfForm;
                m_SceneControl = sceneControl;

                mainfForm.ribbonCheckBoxSun.CheckBoxCheckChanged += RibbonCheckBoxSun_CheckBoxCheckChanged;
                mainfForm.ribbonCheckBoxOcean.CheckBoxCheckChanged += RibbonCheckBoxOcean_CheckBoxCheckChanged;
                mainfForm.ribbonCheckBoxLatLonGrid.CheckBoxCheckChanged += RibbonCheckBoxLatLonGrid_CheckBoxCheckChanged;
                mainfForm.ribbonCheckBoxLatLonGridText.CheckBoxCheckChanged += RibbonCheckBoxLatLonGridText_CheckBoxCheckChanged;
                mainfForm.ribbonCheckBoxNavigation.CheckBoxCheckChanged += RibbonCheckBoxNavigation_CheckBoxCheckChanged;
                mainfForm.ribbonCheckBoxScaleLegend.CheckBoxCheckChanged += RibbonCheckBoxScaleLegend_CheckBoxCheckChanged;
                mainfForm.ribbonCheckBoxStatusBar.CheckBoxCheckChanged += RibbonCheckBoxStatusBar_CheckBoxCheckChanged;
                mainfForm.ribbonCheckBoxTransparency.CheckBoxCheckChanged += RibbonCheckBoxTransparency_CheckBoxCheckChanged;
                
                mainfForm.ribbonTextBoxOpacity.TextBoxTextChanged += RibbonTextBoxOpacity_TextBoxTextChanged;
                mainfForm.ribbonTextBoxOpacity.TextBoxKeyPress += RibbonTextBoxOpacity_TextBoxKeyPress;
                mainfForm.ribbonTextBoxOpacity.TextBoxKeyDown += RibbonTextBoxOpacity_TextBoxKeyDown;

                mainfForm.ribbonCheckBoxAtmosphere.CheckBoxCheckChanged += RibbonCheckBoxAtmosphere_CheckBoxCheckChanged;
                mainfForm.ribbonCheckBoxUnderground.CheckBoxCheckChanged += RibbonCheckBoxUnderground_CheckBoxCheckChanged;
                mainfForm.ribbonCheckBoxFog.CheckBoxCheckChanged += RibbonCheckBoxFog_CheckBoxCheckChanged;

                mainfForm.ribbonButtonPan.Click += RibbonButtonPan_Click;
                mainfForm.ribbonButtonSelect.Click += RibbonButtonSelect_Click;
                mainfForm.ribbonButtonFull.Click += RibbonButtonFull_Click;
                mainfForm.ribbonButtonAddExcavationRegion.Click += RibbonButtonAddExcavationRegion_Click;
                mainfForm.ribbonButtonRemoveExcavationRegion.Click += RibbonButtonRemoveExcavationRegion_Click;
            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex.Message);
            }
        }

        private void RibbonButtonFull_Click(object sender, EventArgs e)
        {
            var lookAtKeys = new List<string>()
                    {
                        "Longitude","Latitude","Tilt","Range","Altitude","Heading"
                    };
            var values = Commons.SerializeHelper.IniHelper.ReadLookAt(lookAtKeys.ToArray());
            LookAt la = new LookAt();
            try
            {
                la = new LookAt()
                {
                    Longitude = double.Parse(values["Longitude"]),
                    Latitude = double.Parse(values["Latitude"]),
                    Tilt = double.Parse(values["Tilt"]),
                    Range = double.Parse(values["Range"]),
                    Altitude = double.Parse(values["Altitude"]),
                    Heading = double.Parse(values["Heading"])
                };
            }
            catch(Exception ex)
            {
                Commons.LogHelper.Error(ex.Message);
                return;
            }
            if(la.IsValid)
                SceneControl.Scene.Fly(la, 1000);
        }

        private void RibbonTextBoxOpacity_TextBoxKeyDown(object sender, KeyEventArgs e)
        {
            var value = GetTransparency();
            if (e.KeyCode == Keys.Down)
            {
                value -= 1;
                if (value < 0) value = 0;
            }
            else if(e.KeyCode == Keys.Up)
            {
                value += 1;
                if (value > 100) value = 100;
            }
            m_FormMain.ribbonTextBoxOpacity.TextBoxText = value.ToString();
        }

        private void RibbonTextBoxOpacity_TextBoxKeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar != '\b')//这是允许输入退格键
            {
                if ((e.KeyChar < '0') || (e.KeyChar > '9'))//这是允许输入0-9数字
                {
                    e.Handled = true;
                }
            }
        }

        private void RibbonTextBoxOpacity_TextBoxTextChanged(object sender, EventArgs e)
        {
            Transparency = GetTransparency();
        }

        private void RibbonButtonRemoveExcavationRegion_Click(object sender, EventArgs e)
        {
            RemoveExcavationRegion();
        }

        private void RibbonButtonAddExcavationRegion_Click(object sender, EventArgs e)
        {
            AddExcavationRegion();
        }

        private void RibbonButtonSelect_Click(object sender, EventArgs e)
        {
            try
            {
                SceneControl.Action = SuperMap.UI.Action3D.Select;
                SceneControl.Scene.Refresh();
            }
            catch (Exception ex)
            {
                Commons.LogHelper.Error(ex.Message);
            }
        }

        private void RibbonButtonPan_Click(object sender, EventArgs e)
        {
            try
            {
                SceneControl.Action = SuperMap.UI.Action3D.Pan;
                SceneControl.Scene.Refresh();
            }
            catch (Exception ex)
            {
                Commons.LogHelper.Error(ex.Message);
            }
        }


        private void RibbonCheckBoxFog_CheckBoxCheckChanged(object sender, EventArgs e)
        {
            Fog = m_FormMain.ribbonCheckBoxFog.Checked;
        }

        private void RibbonCheckBoxUnderground_CheckBoxCheckChanged(object sender, EventArgs e)
        {
            Underground = m_FormMain.ribbonCheckBoxUnderground.Checked;
        }

        private void RibbonCheckBoxAtmosphere_CheckBoxCheckChanged(object sender, EventArgs e)
        {
            Atmosphere = m_FormMain.ribbonCheckBoxAtmosphere.Checked;
        }

        private void RibbonCheckBoxTransparency_CheckBoxCheckChanged(object sender, EventArgs e)
        {
            if (m_FormMain.ribbonCheckBoxTransparency.Checked)
                //Transparency = 50;
                Transparency = GetTransparency();
            else
                Transparency = 0;
            m_FormMain.ribbonTextBoxOpacity.Enabled = m_FormMain.ribbonCheckBoxTransparency.Checked;
        }

        private int GetTransparency() 
        {
            var strVal = m_FormMain.ribbonTextBoxOpacity.TextBoxText;
            int iVal = -1;
            int.TryParse(strVal, out iVal);
            if (iVal < 0) { iVal = 0; m_FormMain.ribbonTextBoxOpacity.TextBoxText = "0"; };
            if (iVal > 100) { iVal = 100; m_FormMain.ribbonTextBoxOpacity.TextBoxText = "100"; };
            return iVal;
        }

        private void RibbonCheckBoxStatusBar_CheckBoxCheckChanged(object sender, EventArgs e)
        {
            StatusBar = m_FormMain.ribbonCheckBoxStatusBar.Checked;
        }

        private void RibbonCheckBoxScaleLegend_CheckBoxCheckChanged(object sender, EventArgs e)
        {
            ScaleLegend = m_FormMain.ribbonCheckBoxScaleLegend.Checked;
        }

        private void RibbonCheckBoxNavigation_CheckBoxCheckChanged(object sender, EventArgs e)
        {
            Navigation = m_FormMain.ribbonCheckBoxNavigation.Checked;
        }

        private void RibbonCheckBoxLatLonGridText_CheckBoxCheckChanged(object sender, EventArgs e)
        {
            LatLonGridText = m_FormMain.ribbonCheckBoxLatLonGridText.Checked;
        }

        private void RibbonCheckBoxLatLonGrid_CheckBoxCheckChanged(object sender, EventArgs e)
        {
            LatLonGrid = m_FormMain.ribbonCheckBoxLatLonGrid.Checked;
            m_FormMain.ribbonCheckBoxLatLonGridText.Enabled = m_FormMain.ribbonCheckBoxLatLonGrid.Checked;
        }

        private void RibbonCheckBoxOcean_CheckBoxCheckChanged(object sender, EventArgs e)
        {
            Ocean = m_FormMain.ribbonCheckBoxOcean.Checked;
        }

        private void RibbonCheckBoxSun_CheckBoxCheckChanged(object sender, EventArgs e)
        {
            Sun = m_FormMain.ribbonCheckBoxSun.Checked;
        }
        /// <summary>
        /// 将三维场景保存到工作空间中
        /// Save the scene to the workspace
        /// </summary>
        public void SaveScene(String sceneName)
        {
            try
            {
                String sceneXml = m_SceneControl.Scene.ToXML();
                Workspace.Scenes.Add(sceneName, sceneXml);
                Workspace.Save();
            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex.Message);
            }
        }
        /// <summary>
        /// 从工作空间中删除当前打开的三维场景
        /// Delete current scene from the workspace
        /// </summary>
        public void DeleteScene()
        {
            try
            {
                String sceneName = m_SceneControl.Scene.Name;

                m_SceneControl.Scene.Close();

                Workspace.Scenes.Remove(sceneName);
                Workspace.Save();
            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex.Message);
            }
        }

        // 构造填挖方区域
        // Construct cutting area
        public void AddExcavationRegion()
        {
            try
            {
                m_SceneControl.Action = Action3D.MeasureArea;
                m_SceneControl.Tracking -= new Tracking3DEventHandler(SceneControl_Tracking);
                m_SceneControl.Tracked -= new Tracked3DEventHandler(SceneControl_Tracked);
                m_SceneControl.Tracking += new Tracking3DEventHandler(SceneControl_Tracking);
                m_SceneControl.Tracked += new Tracked3DEventHandler(SceneControl_Tracked);
            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex.Message);
            }
        }

        // 清除填挖方区域
        // Remove fill/cut area
        public void RemoveExcavationRegion()
        {
            if (m_SceneControl.Scene.GlobalImage.ExcavationRegionCount > 0)
            {
                m_SceneControl.Scene.GlobalImage.ClearExcavationRegions();
            }
        }

        // 绘制多边形时实时显示挖方面积
        // Draw a region to display the cutting area
        private void SceneControl_Tracking(object sender, Tracking3DEventArgs e)
        {
            try
            {
                Point3D loction = new Point3D(0, 0, 0);
                // 获取当前正在绘制的三维几何对象
                // Get the drawing 3D gemometry object
                Geometry3D geometry = e.Geometry;
                Point3D point3D = new Point3D(e.X, e.Y, e.CurrentHeight)
                {
                    Z = m_SceneControl.Scene.GetAltitude(e.X, e.Y)
                };
                Point point = m_SceneControl.Scene.GlobeToPixel(point3D);
                Int32 index = m_SceneControl.Scene.TrackingLayer.IndexOf("area");
                String text = String.Empty;
                if (m_SceneControl.Action == Action3D.MeasureArea && geometry != null)
                {
                    if (index != -1)
                    {
                        m_SceneControl.Scene.TrackingLayer.Remove(index);
                    }
                    if (!(SuperMap.Data.Environment.CurrentCulture == "zh-CN"))
                    {
                        m_Area = "Cutting Area：";
                        m_SquareMeter = "Square Meter";
                    }
                    text = String.Format("{0}{1}{2}", m_Area, e.TotalArea, m_SquareMeter);
                    loction = geometry.InnerPoint3D;
                    GeoText3D geoText = new GeoText3D(new TextPart3D(text, loction));
                    m_SceneControl.Scene.TrackingLayer.Add(geoText, "area");
                }
                else
                {
                    return;
                }
            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex.Message);
            }
        }

        // 绘制结束时将所绘制的区域添加到挖方区域中
        // Add the drawn region to the cutting area after it is drawn
        private void SceneControl_Tracked(object sender, Tracked3DEventArgs e)
        {
            try
            {
                m_Index++;
                Int32 index = m_SceneControl.Scene.TrackingLayer.IndexOf("area");
                if (index != -1)
                {
                    m_SceneControl.Scene.TrackingLayer.Remove(index);
                }

                GeoRegion3D geoRegion3D = e.Geometry as GeoRegion3D;

                m_TextureForm = new TextureForm
                {
                    Location = Cursor.Position
                };
                m_TextureForm.ShowDialog();
                m_TextureForm.FormClosed += TextureForm_FormClosed;

                if (m_TextureForm.GeoStyle3D != null)
                {
                    geoRegion3D.Style3D = m_TextureForm.GeoStyle3D;
                    m_SceneControl.Scene.GlobalImage.AddExcavationRegion(geoRegion3D, "ExcavationRegion" + m_Index);
                    /*
                    Camera camera = new Camera
                    {
                        Longitude = geoRegion3D.InnerPoint3D.X,
                        Latitude = geoRegion3D.InnerPoint3D.Y,
                        AltitudeMode = AltitudeMode.Absolute,
                        Altitude = 25,
                        Tilt = 72.5
                    };
                    m_SceneControl.Scene.Fly(camera);
                    */

                }
                m_SceneControl.Action = Action3D.Pan2;


            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex.Message);
            }
        }

        private void TextureForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            UnRegister();
        }

        internal void CloseScene()
        {
            m_SceneControl.Scene.Close();
        }

        public override void UnRegister()
        {
            m_SceneControl.Tracking -= new Tracking3DEventHandler(SceneControl_Tracking);
            m_SceneControl.Tracked -= new Tracked3DEventHandler(SceneControl_Tracked);
        }

        public void SetMarkerSymbolIDExpression(String expression)
        {
            m_Theme3DCustom.MarkerSymbolIDExpression = expression;
            m_Layer3DDataset.UpdateData();
            m_SceneControl.Scene.Refresh();
        }

        public void SetMarker3DRotateXExpression(String expression)
        {
            m_Theme3DCustom.Marker3DRotateXExpression = expression;
            m_Layer3DDataset.UpdateData();
            m_SceneControl.Scene.Refresh();
        }

        public void SetMarker3DRotateYExpression(String expression)
        {
            m_Theme3DCustom.Marker3DRotateYExpression = expression;
            m_Layer3DDataset.UpdateData();
            m_SceneControl.Scene.Refresh();
        }

        public void SetMarker3DRotateZExpression(String expression)
        {
            m_Theme3DCustom.Marker3DRotateZExpression = expression;
            m_Layer3DDataset.UpdateData();
            m_SceneControl.Scene.Refresh();
        }

        public void SetMarker3DScaleXExpression(String expression)
        {
            m_Theme3DCustom.Marker3DScaleXExpression = expression;
            m_Layer3DDataset.UpdateData();
            m_SceneControl.Scene.Refresh();
        }

        public void SetMarker3DScaleYExpression(String expression)
        {
            m_Theme3DCustom.Marker3DScaleYExpression = expression;
            m_Layer3DDataset.UpdateData();
            m_SceneControl.Scene.Refresh();
        }

        public void SetMarker3DScaleZExpression(String expression)
        {
            m_Theme3DCustom.Marker3DScaleZExpression = expression;
            m_Layer3DDataset.UpdateData();
            m_SceneControl.Scene.Refresh();
        }

        public void SetAltitudeModeExpression(String expression)
        {
            m_Theme3DCustom.AltitudeModeExpression = expression;
            m_Layer3DDataset.UpdateData();
            m_SceneControl.Scene.Refresh();
        }

        public void SetBottomAltitudeExpression(String expression)
        {
            m_Theme3DCustom.BottomAltitudeExpression = expression;
            m_Layer3DDataset.UpdateData();
            m_SceneControl.Scene.Refresh();
        }
    }
}
